import { User } from '@/entity/user.entity';
import { HttpException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RedisService } from '@chenjm/nestjs-redis';
import { Redis, RedisKey } from 'ioredis';
import { UserTempMessage } from '@/dto/user-temp-redis.dto';
import { HTTP_CUSTOM_CODE } from '@/enum/http-custom-code';
import { REDIS_NAME_SPACE } from '@/enum/redis-namespace';
import { BaseResponse } from '@/common/BaseResponse';
import { PhoneLoginDto } from '../auth/dto/phone-login.dto';
import { GENDER } from '@/enum/user';
import { DynamicFollow } from '@/entity/dynamic-follow.entity';
import { WatchUserDto } from './dto/watch-user.dto';
import {
  DNYMIC_LIKE_STATUS,
  DYNAMIC_LIKE_TYPE,
  FOLLOW_STATUS,
} from '@/enum/dynamic';
import { PersonalMessageDto } from './dto/personal-message.dto';
import { DynamicLike } from '@/entity/dynamic-like.entity';
import { Dynamic } from '@/entity/dynamic.entity';
import { RECORD_STATUS } from '@/enum/common';

@Injectable()
export class UserService {
  private readonly redis: Redis;

  constructor(
    @InjectRepository(User) private readonly userRepository: Repository<User>, // 使用泛型注入对应类型的存储库实例
    @InjectRepository(DynamicFollow)
    private readonly dynamicFollowRepository: Repository<DynamicFollow>,
    @InjectRepository(DynamicLike)
    private readonly dynamicLikeRepository: Repository<DynamicLike>,
    @InjectRepository(Dynamic)
    private readonly dynamicRepository: Repository<Dynamic>,
    private readonly redisService: RedisService,
  ) {
    this.redis = this.redisService.getClient();
  }

  setRedis(key: RedisKey, value: string, seconds?: number) {
    const redisKey = REDIS_NAME_SPACE.USER + key;
    if (!seconds) {
      return this.redis.set(redisKey, value);
    } else {
      return this.redis.set(redisKey, value, 'EX', seconds);
    }
  }

  getRedis(key: RedisKey) {
    return this.redis.get(REDIS_NAME_SPACE.USER + key);
  }

  async getUserInfoByRedis<T = any>(id: number): Promise<T | ''> {
    const user = await this.getRedis(String(id));
    return user ? JSON.parse(user) : '';
  }

  async gerUserinfoByUserId(userId: number) {
    return this.userRepository.findOne({
      where: {
        id: userId,
      },
    });
  }

  async getUserInfo(req) {
    const user = await this.getUserInfoByRedis<User>(req.user.id);
    if (user instanceof User && user.status === RECORD_STATUS.DISABLE) {
      return BaseResponse.toError(
        HTTP_CUSTOM_CODE.USER_IS_DISABLE,
        '您已被封禁，无法查询信息！',
      );
    }
    if (user) {
      return BaseResponse.toSuccesJustData(user);
    }
    return BaseResponse.toError(
      HTTP_CUSTOM_CODE.GET_USER_MESSAGE_FAILURE,
      '获取用户信息失败',
    );
  }

  async setUserInfoToRedisByToken(user: User) {
    // 设置用户信息有效期30天
    this.setRedis(String(user.id), JSON.stringify(user), 60 * 60 * 24 * 30);
  }

  findOneByName() {
    return {
      sub: 'string',
      username: 'string',
    };
  }

  async findOneByPhone(phone: string) {
    const userMessage = await this.userRepository.findOneBy({
      phone,
    });
    return userMessage;
  }

  async insertUser(phoneLoginDto: PhoneLoginDto) {
    const user = new User();
    Object.assign(user, phoneLoginDto, {
      gender: GENDER.UNKNONW,
    });
    return this.userRepository.save(user);
  }

  /**
   * 注册临时用户信息
   */
  async setTempUser(userTempMessage: UserTempMessage) {
    try {
      const res = await this.setRedis(
        userTempMessage.token,
        JSON.stringify({
          code: userTempMessage.code,
        }),
        60 * 5,
      );
      return res;
    } catch (error) {
      console.error(error);
      throw new HttpException(
        '设置redis失败',
        HTTP_CUSTOM_CODE.SET_REDIS_FAILURE,
      );
    }
  }

  /**
   * 获取临时注册信息
   */
  async getTempUserMessage(
    token: UserTempMessage['token'],
  ): Promise<UserTempMessage> {
    try {
      const res = await this.getRedis(token);
      if (!res) {
        return Promise.reject(
          new HttpException(
            '验证码不存在',
            HTTP_CUSTOM_CODE.VERIFICATION_CODE_NOT_EXIT,
          ),
        );
      }
      const userTempMessage = JSON.parse(res) as UserTempMessage;
      return userTempMessage;
    } catch (error) {
      console.error(error);
      throw new HttpException(
        '读取redis失败',
        HTTP_CUSTOM_CODE.READ_REDIS_FAILURE,
      );
    }
  }

  async watchUser(watchUserDto: WatchUserDto) {
    // 查询是否已关注
    const result = await this.dynamicFollowRepository.findOne({
      where: {
        userId: watchUserDto.userId,
        targetUserId: watchUserDto.targetUserId,
      },
    });

    if (!result) {
      const like = new DynamicFollow();
      Object.assign(like, {
        userId: watchUserDto.userId,
        targetUserId: watchUserDto.targetUserId,
        status: FOLLOW_STATUS.FOLLOW,
      } as DynamicFollow);
      return BaseResponse.toSucces(
        await this.dynamicFollowRepository.save(like),
        '关注成功',
      );
    }

    if (result.status === FOLLOW_STATUS.FOLLOW) {
      result.status = FOLLOW_STATUS.NOT_FOLLOW;
      await this.dynamicFollowRepository.update(result.id, result);
      return BaseResponse.toSucces(result, '取消关注成功');
    }

    result.status = FOLLOW_STATUS.FOLLOW;
    await this.dynamicFollowRepository.update(result.id, result);
    return BaseResponse.toSucces(result, '关注成功');
  }

  async getPersonalMessage(id: number, selfId: number) {
    const personalMessageDto = new PersonalMessageDto();
    const user = await this.userRepository.findOne({
      where: {
        id: id,
      },
    });
    if (!user) {
      throw new HttpException('用户不存在!', HTTP_CUSTOM_CODE.USER_NOT_FOUND);
    }
    // 获取用户信息
    personalMessageDto.id = user.id;
    personalMessageDto.avatarUrl = user.avatarUrl;
    personalMessageDto.nickName = user.nickName;

    // 获取用户获赞数
    let loveCount = 0;
    // 先查询用户所有动态
    const allDynamic = await this.dynamicRepository.find({
      where: {
        userId: id,
      },
    });
    if (allDynamic) {
      for (let i = 0; i < allDynamic.length; i++) {
        const item = allDynamic[i];
        const itemLoveCount = await this.dynamicLikeRepository.count({
          where: {
            likeTargetId: item.id,
            likeType: DYNAMIC_LIKE_TYPE.DYNAMIC,
            status: DNYMIC_LIKE_STATUS.LIKED,
          },
        });
        loveCount += itemLoveCount;
      }
    }
    personalMessageDto.dynamicLoveCount = loveCount;

    // 获取用户关注用户数
    personalMessageDto.followCount = await this.dynamicFollowRepository.count({
      where: {
        userId: id,
        status: FOLLOW_STATUS.FOLLOW,
      },
    });

    // 获取用户粉丝数
    personalMessageDto.fansCount = await this.dynamicFollowRepository.count({
      where: {
        targetUserId: id,
        status: FOLLOW_STATUS.FOLLOW,
      },
    });

    // 获取关注状态
    if (!selfId) {
      console.log('userId', id);
      personalMessageDto.followStatus = FOLLOW_STATUS.NOT_FOLLOW;
    } else {
      const followResult = await this.dynamicFollowRepository.findOne({
        where: {
          userId: selfId,
          targetUserId: id,
        },
      });
      console.log('followResult', followResult);
      if (followResult) {
        personalMessageDto.followStatus = followResult.status;
      } else {
        personalMessageDto.followStatus = FOLLOW_STATUS.NOT_FOLLOW;
      }
    }
    return personalMessageDto;
  }

  getWathUser(userId: number) {
    console.log('getWathUser-userId', userId);

    const qb = this.dynamicFollowRepository
      .createQueryBuilder('follow')
      .andWhere('follow.user_id = :userId', {
        userId,
      })
      .andWhere('follow.status = :status', {
        status: FOLLOW_STATUS.FOLLOW,
      })
      .leftJoinAndMapOne(
        'follow.targetUserInfo',
        User,
        'user',
        'user.id = follow.target_user_id',
      );
    return qb.getMany();
  }

  getFans(userId: number) {
    console.log('getFans-userId', userId);
    const qb = this.dynamicFollowRepository
      .createQueryBuilder('follow')
      .andWhere('follow.status = :status and follow.target_user_id = :userId', {
        status: FOLLOW_STATUS.FOLLOW,
        userId: userId,
      })
      .leftJoinAndMapOne(
        'follow.targetUserInfo',
        User,
        'user',
        'user.id = follow.user_id',
      );
    return qb.getMany();
  }
}
